#ifndef __W25N01GV_H
#define __W25N01GV_H

#include "main.h"

/*
关于w25n01gv的一些简单说明：
该Flash为NAND Flash，部分指令与w25q系列不同（w25q为NOR Flash）
该产品有2048字节的ID页，2048字节的参数页，以及10个2048字节的OTP(One Time Program)页
芯片总容量128MB，2048+64字节/页，共65536页，可以使用2048字节的输入缓存区进行整页编程
有坏块管理功能，若启用ECC则每页2048字节，后64字节用于保存校验信息，否则每页2112字节
擦除区块大小为128KB，共1024个可擦除区块
SPI时钟最大速率104Mhz
*/

#define FLASH_ID_W25N01GV 0x00EFAA21 //EF表示芯片厂商winbond，AA21表示芯片型号W25N01GV

//状态寄存器标识
#define FLASH_SR_BUSY                                   0x01//芯片忙，正在进行写入或擦除等操作
#define FLASH_SR_WEL                                    0x02//可写标识位
#define FLASH_SR_ERASE_FAIL                             0x04//擦除失败
#define FLASH_SR_WRITE_FAIL                             0x08//编程（写入）失败
#define FLASH_SR_ECC_SUCCESS                            0x00//ECC校验无误
#define FLASH_SR_ECC_LESS_THAN_4BIT_ERR                 0x10//ECC校验有1-4bit的错误，已被纠正
#define FLASH_SR_ECC_MORE_THAN_4BIT_ERR                 0x20//ECC校验有多于4bit的错误，无法被纠正
#define FLASH_SR_ECC_DATA_DAMAGED                       0x30//每页都有多于4bit的错误，不建议继续使用
#define FLASH_SR_BBM_LUT_FULL                           0x40//坏块管理表已满

//坏块链接状态
#define FLASH_LINK_STATUS_MASK                          0xC000//坏块链接状态位掩码
#define FLASH_LINK_AVAILABLE                            0x0000//链接可以使用
#define FLASH_LINK_VALID                                0x8000//该链接正在使用，且链接有效
#define FLASH_LINK_NOT_VALID                            0xC000//该链接被使用过，但现在无效
#define FLASH_LINK_NOT_APPLICABLE                       0x4000//该链接无法使用

//指令
#define FLASH_DEVICE_RESET                              0xFF
#define FLASH_JEDEC_ID                                  0x9F
#define FLASH_READ_STATUS_REGISTER                      0x0F //或0x05
#define FLASH_WRITE_STATUS_REGISTER                     0x1F //或0x01
#define FLASH_STATUS_REG1_ADDR                          0xA0 //低四位可以为任意值
#define FLASH_STATUS_REG2_ADDR                          0xB0 //低四位可以为任意值
#define FLASH_STATUS_REG3_ADDR                          0xC0 //低四位可以为任意值
#define FLASH_WRITE_ENABLE                              0x06
#define FLASH_WRITE_DISABLE                             0x04
#define FLASH_BAD_BLOCK_MANAGEMENT                      0xA1
#define FLASH_READ_BBM_LUT                              0xA5
#define FLASH_LAST_ECC_FAILURE_PAGE_ADDR                0xA9
#define FLASH_BLOCK_ERASE                               0xD8
#define FLASH_PROGRAM_DATA_LOAD                         0x02
#define FLASH_RANDOM_PROGRAM_DATA_LOAD                  0x84
#define FLASH_QUAD_PROGRAM_DATA_LOAD                    0x32
#define FLASH_RANDOM_QUADPROGRAM_DATA_LOAD              0x34
#define FLASH_PROGRAM_ECECUTE                           0x10
#define FLASH_PAGE_DATA_READ                            0x13
#define FLASH_READ                                      0x03
#define FLASH_FAST_READ                                 0x0B
#define FLASH_FAST_READ_WITH_4BYTE_ADDR                 0x0C
#define FLASH_FAST_READ_DUAL_OUTPUT                     0x3B
#define FLASH_FAST_READ_DUAL_OUTPUT_WITH_4BYTE_ADDR     0x3C
#define FLASH_FAST_READ_QUAD_OUTPUT                     0x6B
#define FLASH_FAST_READ_QUAD_OUTPUT_WITH_4BYTE_ADDR     0x6C
#define FLASH_FAST_READ_DUAL_IO                         0xBB
#define FLASH_FAST_READ_DUAL_IO_WITH_4BYTE_ADDR         0xBC
#define FLASH_FAST_READ_QUAD_IO                         0xEB
#define FLASH_FAST_READ_QUAD_IO_WITH_4BYTE_ADDR         0xEC

unsigned char FlashReset(void);
unsigned char FlashInit(void);
unsigned char FlashWaitBusy(unsigned short int timeout);
void FlashWriteEnable(void);
void FlashWriteDisable(void);
unsigned char FlashReadStatusRegister(unsigned char RegAddr);
void FlashWriteStatusRegister(unsigned char RegAddr, unsigned char Value);
unsigned char FlashReadPage(unsigned short int page, unsigned char *buf);
unsigned char FlashWritePage(unsigned short int page, unsigned char *buf);
unsigned char FlashBlockErase(unsigned short int BlockNum);
unsigned char BlockScan(unsigned short int BlockNum);
unsigned char BadBlockScan(unsigned short int BlockNum);
unsigned char BadBlockMapping(unsigned short int LBA, unsigned short int PBA);
void ReadBBMLUT(unsigned short int *BBMLUT);
unsigned short int LastECCFailPageAddr(void);
void BadBlockManage(void);

#endif
